﻿using System;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using System.Windows.Controls;
using System.Windows.Printing;
using AdventureWorksLT.Core;
using AdventureWorksLT.Views.Customers.ChildWindows;
using AdventureWorksLT.Views.Customers.DesignerData;
using AdventureWorksLT.Views.Customers.Reports;
using AdventureWorksLT.Web.Models;
using AdventureWorksLT.Web.Services;
using System.Collections.ObjectModel;
using System.Windows;
using RelayCommand = AdventureWorksLT.Core.RelayCommand;

namespace AdventureWorksLT.Views.Customers.ViewModels
{
    public class SalesOrderHeadersViewModel : PerformAsyncQueryBase // the AsyncQuery one inherits from ViewModel Base
    {
        public static AdventureWorksLTDomainContext SalesOrderHeadersContext;
        private ObservableCollection<SalesOrderHeader> _salesOrderHeaders;
        private AdventureWorksLTDomainContext _context;
        private EntityQuery<AdventureWorksLT.Web.Models.Customer> _customerQuery;
        private EntityQuery<AdventureWorksLT.Web.Models.Address> _shipToAddressQuery;
        private EntityQuery<AdventureWorksLT.Web.Models.Address> _billToAddressQuery;
        private int _pageIndex = 0;
        //
        public SalesOrderHeadersViewModel()
        {
            if (!IsDesignTime)
            {
                SalesOrderHeadersContext = new AdventureWorksLTDomainContext();
                IsBusy = true;
                WireCommands();
                LoadSalesOrderHeadersAsync();
                LoadComboBoxData();
            }
            else
            {
                DesignTimeSalesOrderHeader _designTimeSalesOrderHeader = new DesignTimeSalesOrderHeader();
                SalesOrderHeadersCollection = new ObservableCollection<SalesOrderHeader>(_designTimeSalesOrderHeader.ToList());
                CurrentSalesOrderHeaders = SalesOrderHeadersCollection.FirstOrDefault();
            }
        }
        #region "Load Current SalesOrderHeaders"
        //readonly int loadedCustomerID = AdventureWorksLT.Views.Customers.ViewModels.CustomersViewModel.DashLoad_PK;
        private void LoadSalesOrderHeadersAsync()
        {
           // MessageBox.Show(DashLoad_PK.ToString());
            //DashLoad_PK = 4;
            if (!SalesOrderHeadersContext.IsSubmitting)
            {
                if (DashLoad_PK > 0 && IsFromSalesOrderheader )
                {
                    PerformAsyncQuery<SalesOrderHeader>(SalesOrderHeadersContext, SalesOrderHeadersContext.GetSalesOrderHeadersForSaleOrderNumberQuery(DashLoad_PK), SalesOrderHeadersLoadedComplete);
                }
                if (DashLoad_PK > 0 && !IsFromSalesOrderheader)
                {
                    PerformAsyncQuery<SalesOrderHeader>(SalesOrderHeadersContext, SalesOrderHeadersContext.GetSalesOrderHeadersForCustomerQuery(DashLoad_PK), SalesOrderHeadersLoadedComplete);
                }
                
                else
                {
                    PerformAsyncQuery<SalesOrderHeader>(SalesOrderHeadersContext, SalesOrderHeadersContext.GetSalesOrderHeadersQuery(), SalesOrderHeadersLoadedComplete);
                }
            }
        }
        private ObservableCollection<SalesOrderHeader> _salesOrderHeadersCollection;
        public ObservableCollection<SalesOrderHeader> SalesOrderHeadersCollection
        {
            get { return _salesOrderHeadersCollection; }
            set
            {
                _salesOrderHeadersCollection = value;
                RaisePropertyChanged("SalesOrderHeadersCollection");
            }
        }

        private SalesOrderHeader _currentSalesOrderHeaders;
        public SalesOrderHeader CurrentSalesOrderHeaders
        {
            get { return _currentSalesOrderHeaders; }
            set
            {
                _currentSalesOrderHeaders = value;
                RaisePropertyChanged("CurrentSalesOrderHeaders");
            }
        }
        #endregion "Load Current SalesOrderHeaders"
        #region Commands
        private void EnableCommands()
        {
            AddNewCommand.IsEnabled = true;
            EditCurrentInNewWindowCommand.IsEnabled = true;
            SaveCommand.IsEnabled = true;
            DeleteCommand.IsEnabled = true;
            PrintCommand.IsEnabled = true;
            SearchSalesOrderHeadersCommand.IsEnabled = true;
            ShowChartDashboardCommand.IsEnabled = true;
            SelectionChangedSdkCommand.IsEnabled = true;
            RowLoadingSdkCommand.IsEnabled = true;
            PreviousPageCommand.IsEnabled = true;
            NextPageCommand.IsEnabled = true;
        }
        private void WireCommands()
        {
            AddNewCommand = new RelayCommand(AddSalesOrderHeaders);
            EditCurrentInNewWindowCommand = new RelayCommand(EditCurrentInNewWindow);
            SaveCommand = new RelayCommand(SaveSalesOrderHeaders);
            DeleteCommand = new RelayCommand(DeleteSalesOrderHeaders);
            PrintCommand = new RelayCommand(PrintSalesOrderHeaders);
            ShowChartDashboardCommand = new RelayCommand<object>(ShowChartDashboard);
            SearchSalesOrderHeadersCommand = new RelayCommand<string>(SearchInSalesOrderHeaders);
            SelectionChangedSdkCommand = new RelayCommand<SalesOrderHeader>(OnExecuteSelectionChangedSDK);
            RowLoadingSdkCommand = new RelayCommand<System.Windows.Controls.DataGridRowEventArgs>(OnExecuteRowLoadingSDK);
            PreviousPageCommand = new RelayCommand(PreviousPage);
            NextPageCommand = new RelayCommand(NextPage);
        }



        private void OnExecuteRowLoadingSDK(System.Windows.Controls.DataGridRowEventArgs e)
        {
            AdventureWorksLT.Web.Models.SalesOrderHeader model = e.Row.DataContext as AdventureWorksLT.Web.Models.SalesOrderHeader;

            var grid = new Grid();
            var tb = new TextBlock
            {
                Text = string.Format(
                     "Revision Number : {0} \r\n" + "Order Date : {1} \r\n" + "Due Date : {2} \r\n" + "Ship Date : {3} \r\n" + "Status : {4} \r\n" + "Online Order Flag : {5} \r\n" + "Sales Order Number : {6} \r\n" + "Purchase Order Number : {7} \r\n" + "Account Number : {8} \r\n" + "Ship Method : {9} \r\n" + "Credit Card Approval Code : {10} \r\n" + "Sub Total : {11} \r\n" + "Tax Amt : {12} \r\n" + "Freight : {13} \r\n" + "Total Due : {14} \r\n" + "Comment : {15} \r\n" + "Rowguid : {16} \r\n" + "Modified Date : {17} \r\n",
                     model.RevisionNumber, model.OrderDate, model.DueDate, model.ShipDate, model.Status, model.OnlineOrderFlag, model.SalesOrderNumber, model.PurchaseOrderNumber, model.AccountNumber, model.ShipMethod, model.CreditCardApprovalCode, model.SubTotal, model.TaxAmt, model.Freight, model.TotalDue, model.Comment, model.rowguid, model.ModifiedDate),
                Margin = new Thickness(3, 3, 3, 3),
                Opacity = 0.8,
                MaxWidth = 250,
                FontSize = 10,
                TextWrapping = TextWrapping.NoWrap
            };
            grid.Children.Add(tb);
            ToolTipService.SetToolTip(e.Row, grid);
        }
        private void OnExecuteSelectionChangedSDK(SalesOrderHeader CheckedSalesOrderHeaders)
        {

            CurrentSalesOrderHeaders = CheckedSalesOrderHeaders;
            SelectedCustomer =
            CustomerCollection.Where(c => CurrentSalesOrderHeaders != null && c.CustomerID == CurrentSalesOrderHeaders.CustomerID).SingleOrDefault();
            SelectedShipToAddress =
            ShipToAddressCollection.Where(c => CurrentSalesOrderHeaders != null && c.AddressID == CurrentSalesOrderHeaders.ShipToAddressID).SingleOrDefault();
            SelectedBillToAddress =
            BillToAddressCollection.Where(c => CurrentSalesOrderHeaders != null && c.AddressID == CurrentSalesOrderHeaders.BillToAddressID).SingleOrDefault();
        }

        private void NextPage()
        {
            _pageIndex++;
            SalesOrderHeadersCollection = new ObservableCollection<SalesOrderHeader>(SalesOrderHeadersContext.SalesOrderHeaders.Skip(_pageIndex * 20).Take(20));
            CurrentSalesOrderHeaders = SalesOrderHeadersCollection.FirstOrDefault();
        }

        private void PreviousPage()
        {
            _pageIndex--;
            SalesOrderHeadersCollection = new ObservableCollection<SalesOrderHeader>(SalesOrderHeadersContext.SalesOrderHeaders.Skip(_pageIndex * 20).Take(20));
            CurrentSalesOrderHeaders = SalesOrderHeadersCollection.FirstOrDefault();
        }

        public RelayCommand<System.Windows.Controls.DataGridRowEventArgs> RowLoadingSdkCommand
        {
            get;
            private set;
        }
        public RelayCommand<SalesOrderHeader> SelectionChangedSdkCommand
        {
            get;
            private set;
        }
        public RelayCommand PreviousPageCommand
        {
            get;
            private set;
        }
        public RelayCommand NextPageCommand
        {
            get;
            private set;
        }

        public RelayCommand AddNewCommand
        {
            get;
            private set;
        }

        public RelayCommand EditCurrentInNewWindowCommand
        {
            get;
            private set;
        }

        public RelayCommand SaveCommand
        {
            get;
            private set;
        }

        public RelayCommand DeleteCommand
        {
            get;
            private set;
        }

        public RelayCommand PrintCommand
        {
            get;
            private set;
        }

        public RelayCommand<object> ShowChartDashboardCommand
        {
            get;
            private set;
        }

        public RelayCommand<string> SearchSalesOrderHeadersCommand
        {
            get;
            private set;
        }
        #endregion Commands

        private void SearchInSalesOrderHeaders(string searchText)
        {
            MessageBox.Show(searchText);
        }
        public void SaveSalesOrderHeaders()
        {
            CurrentSalesOrderHeaders.CustomerID = SelectedCustomer.CustomerID;
            CurrentSalesOrderHeaders.ShipToAddressID = SelectedShipToAddress.AddressID;
            CurrentSalesOrderHeaders.BillToAddressID = SelectedBillToAddress.AddressID;
            SalesOrderHeadersContext.SubmitChanges(OnCallbackSave, null);
        }
        private void OnCallbackSave(SubmitOperation p)
        {
            if (p.HasError)
            {
                p.MarkErrorAsHandled();
                ErrorWindow.CreateNew(p.Error);
            }
            else
            {
                MessageBox.Show("SalesOrderHeaders has been updated");
                RaisePropertyChanged("SalesOrderHeadersCollection");
                RaisePropertyChanged("CurrentSalesOrderHeaders");
            }
        }
        #region "Add New & Edit"
        //http://forums.silverlight.net/forums/p/193377/449256.aspx
        private void AddSalesOrderHeaders()
        {
            AdventureWorksLT.Web.Models.SalesOrderHeader salesOrderHeaders = new AdventureWorksLT.Web.Models.SalesOrderHeader();
            SalesOrderHeaderAddCW addNewWindow = new SalesOrderHeaderAddCW();
            addNewWindow.DataContext = salesOrderHeaders;
            addNewWindow.Closed += (s, ee) =>
            {
                if (addNewWindow.DialogResult == true)
                {
                    SalesOrderHeadersContext.SalesOrderHeaders.Add(salesOrderHeaders);
                    SalesOrderHeadersContext.SubmitChanges(p =>
                    {
                        if (p.HasError)
                        {
                            p.MarkErrorAsHandled();
                            ErrorWindow.CreateNew(p.Error);
                        }

                        else
                        {
                            MessageBox.Show("New SalesOrderHeaders has been added");
                        }
                    }, null);
                }

            };
            addNewWindow.Show();
            addNewWindow.Closed += FrmClosedAdd;
        }

        void FrmClosedAdd(object sender, EventArgs e)
        {
            DashLoad_PK = 0; // to load all SalesOrderHeaders
            // The only time that the DashLoad_PK does not need to be made zero, is when what is closing is the Child Grid in a master-Child Invoice type.
            // Because the details Grid needs to keep the filter, is a Details for one particular header invoice

            LoadSalesOrderHeadersAsync();
        }

        public static bool IsFromSalesOrderheader;
        public static int CSalesOrderID;
        private void ObtainSalesOrderID()
        {

            string a = CurrentSalesOrderHeaders.SalesOrderID.ToString();
            int dashLoadPk;
            int.TryParse(a, out dashLoadPk);
            DashLoad_PK = dashLoadPk;
            CSalesOrderID = dashLoadPk;

        }

        private void EditCurrentInNewWindow()
        {
            ObtainSalesOrderID();
            if (CSalesOrderID > 0)
            {
                
                var frm = new ChildWindows.SalesOrderHeaderCW();
                frm.Show();
                frm.Closed += new System.EventHandler(FrmClosed);
            }
        }

        void FrmClosed(object sender, System.EventArgs e)
        {
            DashLoad_PK = 0;
            // The only time that the DashLoad_PK does not need to be made zero, is when what is closing is the Child Grid in a master-Child Invoice type.
            // Because the details Grid needs to keep the filter, is a Details for one particular header invoice
            LoadSalesOrderHeadersAsync();
        }



        #endregion "Add New & Edit"

        private static int _dashload_PK;
        public static int DashLoad_PK
        {
            get { return _dashload_PK; }
            set { _dashload_PK = value; }
        }

        private void ShowChartDashboard(object selectedItem)
        {
            string a = selectedItem.ToString();
            int i = a.IndexOf(":") + 1;
            a = a.Substring(i);
            int dashLoadPk;
            int.TryParse(a, out dashLoadPk);
            DashLoad_PK = dashLoadPk;
            Uri target = new Uri("/Customers/Pages/PatientsTitlePage?SalesOrderID=" + DashLoad_PK, UriKind.Relative);
            var _theItem = selectedItem;
            CurrentSalesOrderHeaders = (SalesOrderHeader)_theItem;
            //NavigationService.Navigate(target);
            //var service = ((Page)((App)Application.Current).RootVisual).NavigationService;
            //if (service != null) service.Navigate(target);
        }

        private bool _isBusy;
        public bool IsBusy
        {
            get { return _isBusy; }
            set
            {
                _isBusy = value;
                RaisePropertyChanged("IsBusy");
            }
        }





        public string CurrentTime
        {
            get
            {
                DateTime time = DateTime.Now;
                const string format = "MMM ddd d HH:mm yyyy";
                return (time.ToString(format));
            }
        }

        #region "Security"
        //Security methods
        private void CheckSecurity()
        {
            // Add code for LoggedIn and LoggedOut events
            WebContext.Current.Authentication.LoggedIn += Authentication_Changed;
            WebContext.Current.Authentication.LoggedOut += Authentication_Changed;
        }

        void Authentication_Changed(object sender, System.ServiceModel.DomainServices.Client.ApplicationServices.AuthenticationEventArgs e)
        {
            RaisePropertyChanged("IsAdmin");
        }

        private bool _IsAdmin;
        public bool IsAdmin
        {
            get { return CheckUserIsInRole("Admin"); }
        }

        private bool CheckUserIsInRole(string role)
        {
            return WebContext.Current.User.IsInRole(role);
        }

        //<HyperlinkButton x:Name="AdminLink" Visibility="{Binding IsAdmin,Converter={StaticResource BoolToVisibilityConverter},FallbackValue=Collapsed}" TargetName="ContentFrame" NavigateUri="/AdminView" Content="Admin" Style="{StaticResource LinkStyle}" />
        // CurrentUser is needed for logging
        public string CurrentUser
        {
            get { return WebContext.Current.User.ToString(); }
        }

        #endregion "Security"

        #region "LoadComboBoxData"
        public EntitySet<Customer> CustomerCollection { get; set; }
        private Customer _selectedCustomer;
        public Customer SelectedCustomer
        {
            get { return _selectedCustomer; }
            set
            {
                _selectedCustomer = value;
                RaisePropertyChanged("SelectedCustomer");
            }
        }
        public EntitySet<Address> ShipToAddressCollection { get; set; }
        private Address _selectedShipToAddress;
        public Address SelectedShipToAddress
        {
            get { return _selectedShipToAddress; }
            set
            {
                _selectedShipToAddress = value;
                RaisePropertyChanged("SelectedShipToAddress");
            }
        }
        public EntitySet<Address> BillToAddressCollection { get; set; }
        private Address _selectedBillToAddress;
        public Address SelectedBillToAddress
        {
            get { return _selectedBillToAddress; }
            set
            {
                _selectedBillToAddress = value;
                RaisePropertyChanged("SelectedBillToAddress");
            }
        }
        private long dtStart = 0;
        private long dtEnd = 0;
        void LoadComboBoxData()
        {
            dtStart = System.DateTime.Now.Ticks;
            //CustomerIDComboBox
            _context = new AdventureWorksLTDomainContext();
            _customerQuery = _context.GetCustomersQuery();
            _customerQuery = _customerQuery.OrderBy(e => e.CustomerID);
            PerformAsyncQuery<Customer>(_context, _customerQuery, CustomerIDComboBoxLoaded);
            CustomerCollection = _context.Customers;
            //ShipToAddressIDComboBox
            _context = new AdventureWorksLTDomainContext();
            _shipToAddressQuery = _context.GetAddressesQuery();
            _shipToAddressQuery = _shipToAddressQuery.OrderBy(e => e.AddressID);
            PerformAsyncQuery<Address>(_context, _shipToAddressQuery, ShipToAddressIDComboBoxLoaded);
            ShipToAddressCollection = _context.Addresses;
            //BillToAddressIDComboBox
            _context = new AdventureWorksLTDomainContext();
            _billToAddressQuery = _context.GetAddressesQuery();
            _billToAddressQuery = _billToAddressQuery.OrderBy(e => e.AddressID);
            PerformAsyncQuery<Address>(_context, _billToAddressQuery, BillToAddressIDComboBoxLoaded);
            BillToAddressCollection = _context.Addresses;
        }
        private void CustomerIDComboBoxLoaded(object sender, AdventureWorksLT.Core.EntityResultsArgs<Customer> e)
        {
            if (!e.HasError)
            {
                SelectedCustomer =
                CustomerCollection.Where(c => c.CustomerID == CurrentSalesOrderHeaders.CustomerID).SingleOrDefault();
            }
        }
        private void ShipToAddressIDComboBoxLoaded(object sender, AdventureWorksLT.Core.EntityResultsArgs<Address> e)
        {
            if (!e.HasError)
            {
                SelectedShipToAddress =
                ShipToAddressCollection.Where(c => c.AddressID == CurrentSalesOrderHeaders.ShipToAddressID).SingleOrDefault();
            }
        }
        private void BillToAddressIDComboBoxLoaded(object sender, AdventureWorksLT.Core.EntityResultsArgs<Address> e)
        {
            if (!e.HasError)
            {
                SelectedBillToAddress =
                BillToAddressCollection.Where(c => c.AddressID == CurrentSalesOrderHeaders.BillToAddressID).SingleOrDefault();
            }
        }
        private void SalesOrderHeadersLoadedComplete(object sender, AdventureWorksLT.Core.EntityResultsArgs<SalesOrderHeader> e)
        {
            IsBusy = false;
            //IsFromSalesOrderheader = false;
            // this is to be assigned at SalesOrderHeaderCW : ChildWindow
            // before initializing the UI.. is is done here, it will be false
            if (!e.HasError)
            {
                //SalesOrderHeadersCollection = SalesOrderHeadersContext.SalesOrderHeader;
                SalesOrderHeadersCollection = new ObservableCollection<SalesOrderHeader>(SalesOrderHeadersContext.SalesOrderHeaders.OrderBy(c => c.SalesOrderID).Take(20));
                CurrentSalesOrderHeaders = SalesOrderHeadersCollection.FirstOrDefault();
                EnableCommands();
                SelectedCustomer = CustomerCollection.Where(c => c.CustomerID == CurrentSalesOrderHeaders.CustomerID).SingleOrDefault();
                SelectedShipToAddress = ShipToAddressCollection.Where(c => c.AddressID == CurrentSalesOrderHeaders.ShipToAddressID).SingleOrDefault();
                SelectedBillToAddress = BillToAddressCollection.Where(c => c.AddressID == CurrentSalesOrderHeaders.BillToAddressID).SingleOrDefault();
            }
            else
            {
                // notify user if there is any error
                //AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }



        private void AddNewForm_Closed(object sender, AdventureWorksLT.Core.EntityResultsArgs<SalesOrderHeader> e)
        {
            if (!e.HasError)
            {
            }
        }
        #endregion "LoadComboBoxData"
        #region "Delete"
        private bool _toDelete = false;
        private void DeleteSalesOrderHeaders()
        {
            _toDelete = true;
            var salesOrderHeadersToDelete = CurrentSalesOrderHeaders;
            if (salesOrderHeadersToDelete != null)
            {
                var result = MessageBox.Show("Are you sure you wish to delete the Current SalesOrderHeaders?", "Confirm Delete", MessageBoxButton.OKCancel);
                if (result.Equals(MessageBoxResult.OK))
                {
                    SalesOrderHeadersContext.SalesOrderHeaders.Remove(salesOrderHeadersToDelete);
                    SalesOrderHeadersContext.SubmitChanges(o =>
                    {
                        if (o.HasError)
                        {
                            MessageBox.Show("Esta salesOrderHeaders no se puede eliminar ya que existen datos que dependen de esta SalesOrderHeaders.....", "Cancelado", MessageBoxButton.OKCancel);
                            o.MarkErrorAsHandled();
                            SalesOrderHeadersContext.RejectChanges();
                        }
                        else
                        {
                            MessageBox.Show("The record salesOrderHeaders has been deleted ... ");

                            DashLoad_PK = 0; // to load all SalesOrderHeaders

                            // The only time that the DashLoad_PK does not need to be made zero, is when what is closing is the Child Grid in a master-Child Invoice type.
                            // Because the details Grid needs to keep the filter, is a Details for one particular header invoice
                            LoadSalesOrderHeadersAsync();

                        }
                    }, null);
                }
            }
            _toDelete = false;
        }
        #endregion "Delete"
        #region "Print"
        private void PrintSalesOrderHeaders()
        {
            if (CurrentSalesOrderHeaders != null)
            {
                PrintDocument document = new PrintDocument();
                document.PrintPage += new System.EventHandler<PrintPageEventArgs>(document_PrintPage); // fires when every single page is going to print 
                document.EndPrint += new System.EventHandler<EndPrintEventArgs>(document_EndPrint); // when printing is completed
                string PrintQueue = "SalesOrderHeader_" + CurrentSalesOrderHeaders.ToString(); // to show in the print queue
                document.Print(PrintQueue); //fires when printing has begun
            }
        }
        static void document_EndPrint(object sender, EndPrintEventArgs e)
        {
            if (e.Error != null)
            {
                ErrorWindow error = new ErrorWindow(e.Error.Message, e.Error.StackTrace);
            }
            else
                MessageBox.Show("Print Complete");
        }
        void document_PrintPage(object sender, PrintPageEventArgs e)
        {
            PrintDocument document = sender as PrintDocument;
            AdventureWorksLT.Web.Models.SalesOrderHeader appt = CurrentSalesOrderHeaders as AdventureWorksLT.Web.Models.SalesOrderHeader;
            if (appt != null)
            {
                //e.HasMorePages = appt.ChildEntity != null && document.PrintedPageCount < appt.ChildEntity.Count;
                //if (document.PrintedPageCount > 0)
                //{
                // e.PageVisual = new ChildEntityFReport() { DataContext = appt.ChildEntity.ElementAt(document.PrintedPageCount - 1) };
                //}
                //else

                // in case i need to print the Invoice
                //e.PageVisual = new SalesOrderHeaderFReport() { DataContext = appt };
            }
        }
        #endregion "Print"
    }
}